package pulpfizz.pulp.body;

import org.jbox2d.dynamics.Body;
import pulpcore.animation.BindFunction;
import pulpcore.image.Colors;
import pulpcore.math.CoreMath;
import pulpcore.sprite.FilledSprite;
import pulpcore.sprite.Sprite;
import pulpfizz.physics.BodyUtils;
import pulpfizz.pulp.CanvasPoint;
import pulpfizz.pulp.FizzScene;
import pulpfizz.pulp.PhysicsPoint;

import java.awt.geom.Rectangle2D;
import java.util.List;

public class BodySprite
{
	Body body;
	Sprite sprite;
	
	double offsetX;
	double offsetY;

	public BodySprite(Body body)
	{
		this(body, null);
	}

	public BodySprite(Body body, Sprite sprite)
	{
		this.body = body;
		this.sprite = sprite;

		if (sprite == null)
		{
			// TODO: Create a default sprite for the body, and add to the physics canvas.
			Sprite s = new FilledSprite(Colors.BLUE);
			s.x.bindTo(bindX());
			s.y.bindTo(bindY());
			s.angle.bindTo(bindAngle());
			
			FizzScene.getCanvas().add(sprite);
		}
	}

	public BindFunction bindX()
	{
		return new BindFunction()
		{
			public Number f()
			{
				CanvasPoint cp = getPosition();
				double x = cp.getX();
//				double f = physics.getCanvasX(body);
//				double angle = physics.getCanvasAngle(body);
				double angle = body.getAngle();
				double xCos = offsetX * CoreMath.toDouble(CoreMath.cos(CoreMath.toFixed(angle)));
				double ySin = offsetY * CoreMath.toDouble(CoreMath.sin(CoreMath.toFixed(angle)));
				return x + xCos - ySin;
			}
		};
	}
	
	public BindFunction bindY()
	{
		return new BindFunction()
		{
			public Number f()
			{
//				double f = physics.getCanvasY(body);
				CanvasPoint cp = getPosition();
				double y = cp.getY();
//				double angle = physics.getCanvasAngle(body);
				double angle = body.getAngle();
				double xSin = offsetX * CoreMath.toDouble(CoreMath.sin(CoreMath.toFixed(angle)));
				double yCos = offsetY * CoreMath.toDouble(CoreMath.cos(CoreMath.toFixed(angle)));
				return y + xSin + yCos;
			}
		};
	}

	
	BindFunction bindAngle()
	{
		return new BindFunction()
		{
			public Number f()
			{
				return (body.getAngle());
			}
		};
	}
	
	public BodySprite(CanvasPoint circleCenter, double circleRadius)
	{
		this(BodyUtils.createCircle(circleCenter, circleRadius));
	}

	public BodySprite(java.awt.Shape shape)
	{
		this(BodyUtils.createFromShape(shape));
	}

	public BodySprite(List<CanvasPoint> points)
	{
		this(BodyUtils.createPolygon(points));
	}

	public BodySprite(String svgFile, Rectangle2D.Float rect)
	{
		this(BodyUtils.createFromSVG(svgFile, rect));
	}

	public CanvasPoint getCenterOfMass()
	{
		PhysicsPoint p = new PhysicsPoint(body.getWorldCenter().x, body.getWorldCenter().y);
		return FizzScene.toCanvas(p);
	}
	
	public CanvasPoint getPosition()
	{
		PhysicsPoint p = new PhysicsPoint(body.getPosition().x, body.getPosition().y);
		return FizzScene.toCanvas(p);
	}
}
